home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Format / rfc1148 / P2toRFC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  53.8 KB  |  2,488 lines

  1. /* P2toRFC.c: p2 msg + optional p1 struct + optional bodypart -> RFC 822 hdr */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $
  9.  *
  10.  * $Log: P2toRFC.c,v $
  11.  * Revision 6.0  1991/12/18  20:20:34  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "head.h"
  19. #include "util.h"
  20. #include "IOB-types.h"
  21. #include "Ext-types.h"
  22. #include "q.h"
  23. #include <isode/cmd_srch.h>
  24. #include "tb_bpt88.h"
  25. #include "or.h"
  26. #include "ap.h"
  27. #include "oids.h"
  28. #include "charset.h"
  29.  
  30. static int load_time(), load_addr();
  31. static FILE *fp_out;
  32. static struct type_IOB_Heading *head;
  33. static struct type_IOB_IPN *ipn;
  34. static char    ipn_body[MAXPATHLENGTH];
  35. static char abuf [BUFSIZ];
  36. static int decode_extension();
  37. static int decode_ext_char (), decode_ext_rdm(),
  38.     decode_ext_pdm(), decode_ext_int(), decode_ext_rnfa(),
  39.     decode_ext_pra(), decode_ext_redir(), ext_decode_dlexph();
  40. static Q_struct    del_info_q;
  41. static ADDR del_info_recip;
  42.  
  43. extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */];
  44. extern CMD_TABLE atbl_rdm[], atbl_pd_modes[], atbl_reg_mail[];
  45. extern char    *cont_p2, *cont_p22;
  46. extern char    *hdr_822_bp, *hdr_p2_bp, *ia5_bp, *hdr_p22_bp, *hdr_ipn_bp;
  47. extern char *dn2str ();
  48. extern int    msgid2rfc(), encinfo2rfc();
  49. extern int    order_pref;
  50. extern UTC    utclocalise();
  51. int        convertresult;
  52. extern char    *dn2ufn(), *oid2lstr();
  53. static int    firstLine;
  54.  
  55. #define bit_ison(x,y)        (bit_test(x,y) == 1)
  56.  
  57. P2toRFC (p2_in, ext_in, qp, del_info, rfc_out, ipn_body_out, ep)
  58. char        *p2_in;
  59. char        *ext_in;
  60. Q_struct       *qp;
  61. char        *del_info;
  62. char        *rfc_out;
  63. char        *ipn_body_out;
  64. char        **ep;
  65. {
  66.     FILE    *fp_in;
  67.     PE    pe = NULLPE;
  68.     PS    ps = NULLPS;
  69.     int    retval, ishead;
  70.     char    *ix;
  71.     char    buf[BUFSIZ];
  72.  
  73.     head = NULL;
  74.     ipn = NULL;
  75.     firstLine = TRUE;
  76.     convertresult = OK;
  77.  
  78.     if ((ix = rindex(p2_in, '/')) == NULL)
  79.         ix = p2_in;
  80.     else
  81.         ix++;
  82.  
  83.     if (lexnequ(ix, hdr_p2_bp, strlen(hdr_p2_bp)) == 0
  84.         || lexnequ(ix, hdr_p22_bp, strlen(hdr_p22_bp)) == 0)
  85.         ishead = OK;
  86.     else if (lexnequ(ix, hdr_ipn_bp, strlen(hdr_ipn_bp)) == 0)
  87.         ishead = NOTOK;
  88.     else {
  89.         (void) sprintf(buf,
  90.                    "Unknown x400 hdr type '%s'",
  91.                    ix);
  92.         PP_LOG(LLOG_EXCEPTIONS,
  93.                ("%s", buf));
  94.         *ep = strdup(buf);
  95.         return (NOTOK);
  96.     }
  97.     
  98.     if (rfc_out == NULLCP)
  99.         fp_out = stdout;
  100.     else if ((fp_out = fopen (rfc_out, "w")) == NULL)
  101.     {
  102.         PP_SLOG (LLOG_EXCEPTIONS, rfc_out,
  103.              ("Can't open file"));
  104.         (void) sprintf (buf,
  105.                 "Failed to open output file '%s'", 
  106.                 rfc_out);
  107.         *ep = strdup(buf);
  108.         return (NOTOK);
  109.     }
  110.  
  111.     if (ipn_body_out)
  112.         strcpy(ipn_body, ipn_body_out);
  113.     else
  114.         ipn_body[0] = '\0';
  115.  
  116.     if (p2_in == NULLCP)
  117.         fp_in = stdin;
  118.     else if ((fp_in = fopen (p2_in, "r")) == NULL)
  119.     {
  120.         PP_SLOG (LLOG_EXCEPTIONS, p2_in,
  121.              ("Can't open file"));
  122.         fclose (fp_out);
  123.         (void) sprintf (buf,
  124.                 "Failed to open input file '%s'",
  125.                 p2_in);
  126.         *ep = strdup(buf);
  127.         return (NOTOK);
  128.     }
  129.  
  130.     if (((ps = ps_alloc (std_open)) == NULLPS) ||
  131.         (std_setup (ps, fp_in) == NOTOK))
  132.     {
  133.         PP_LOG (LLOG_EXCEPTIONS, ("p2to822() failed to setup PS"));
  134.         retval = NOTOK;
  135.         *ep = strdup("Failed to set up PS");
  136.         goto cleanup;
  137.     }
  138.  
  139.  
  140.     if ((pe = ps2pe (ps)) == NULLPE)
  141.     {
  142.         PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error on file '%s'", p2_in));
  143.         retval = NOTOK;
  144.         goto cleanup;
  145.     }
  146.  
  147.     PY_pepy[0] = 0;
  148.     if (ishead == OK) {
  149.         if (decode_IOB_Heading (pe, 0, NULLIP, NULLVP, &head) != OK)
  150.         {
  151.             PP_OPER(NULLCP,
  152.                 ("decode_IOB_heading() failed : [%s]", PY_pepy));
  153.             retval = NOTOK;
  154.             convertresult = NOTOK;
  155.             abort();
  156.             *ep = strdup("Illegal ASN.1 in IOB Heading");
  157.             goto cleanup;
  158.         }
  159.        
  160.         if (PY_pepy[0] != 0)
  161.             PP_LOG(LLOG_EXCEPTIONS,
  162.                    ("decode_IOB_heading non-fatal failure [%s]", PY_pepy));
  163.  
  164.  
  165.         if (qp != (Q_struct *) NULL
  166.             && do_p1 (qp, ishead, ep) != OK)
  167.         {
  168.             PP_TRACE (("P1 output failure"));
  169.             retval = NOTOK;
  170.             goto cleanup;
  171.         }
  172.  
  173.         if (NULLCP != del_info
  174.             && do_delinfo (del_info, ep) != OK)
  175.         {
  176.             PP_TRACE (("Delivery Info output failure"));
  177.             retval = NOTOK;
  178.             goto cleanup;
  179.         }
  180.  
  181.         if (do_p2_head (ep) != OK)
  182.         {
  183.             PP_TRACE (( "P2 output failure"));
  184.             retval = NOTOK;
  185.             goto cleanup;
  186.         }
  187.  
  188.     } else {
  189.         if (decode_IOB_IPN (pe, 0, NULLIP, NULLVP, &ipn) != OK)
  190.         {
  191.             PP_OPER(NULLCP,
  192.                 ("decode_IOB_IPN() failed : [%s]", PY_pepy));
  193.             retval = NOTOK;
  194. /*            convertresult = NOTOK;*/
  195.             *ep = strdup("Illegal ASN.1 in IPN");
  196.             goto cleanup;
  197.         }
  198.         
  199.         if (PY_pepy[0] != 0)
  200.             PP_LOG(LLOG_EXCEPTIONS,
  201.                    ("decode_IOB_IPN non-fatal failure [%s]",
  202.                 PY_pepy));
  203.  
  204.         if ((Q_struct *) NULL != qp
  205.             && do_p1_ipn (qp, ishead, ep) != OK)
  206.         {
  207.             PP_TRACE (("P1 output failure"));
  208.             retval = NOTOK;
  209.             goto cleanup;
  210.         }
  211.  
  212.         if (NULLCP != del_info
  213.             && do_delinfo (del_info, ep) != OK)
  214.         {
  215.             PP_TRACE(("Delivery Info output failure"));
  216.             retval = NOTOK;
  217.             goto cleanup;
  218.         }
  219.  
  220.         if (do_p2_ipn(qp, ep) != OK)
  221.         {
  222.             PP_TRACE (("P2 output failure"));
  223.             retval = NOTOK;
  224.             goto cleanup;
  225.         }
  226.  
  227.     }
  228.     do_same_line ("\n");    /* Terminate header */
  229.  
  230.     if (do_extra (ext_in, ep) != OK)
  231.     {
  232.         PP_TRACE (( "Extra bits output failure"));
  233.         retval = NOTOK;
  234.         goto cleanup;
  235.     }
  236.     
  237.     if (ishead != OK
  238.         && do_p2_ipn_body(qp, ep) != OK)
  239.     {
  240.         PP_TRACE((" IPN body output failure"));
  241.         retval = NOTOK;
  242.         goto cleanup;
  243.     }
  244.  
  245.     retval = OK;
  246.     cleanup:
  247.     fclose (fp_out);
  248.     fclose (fp_in);
  249.     
  250.     if (pe != NULLPE) pe_free(pe);
  251.     if (ps != NULLPS) ps_free(ps);
  252.     if (head != NULL) free_IOB_Heading (head);
  253.     if (ipn != NULL) free_IOB_IPN (ipn);
  254.     return (retval);
  255. }
  256.  
  257. /*   */
  258.  
  259. /* ARGSUSED */
  260. do_p2_head(ep)
  261. char    **ep;
  262. {
  263.     int    haveTo = FALSE;
  264.  
  265.     if (head -> authorizing__users != NULL) {
  266.         do_key ("From");
  267.         do_ORD_seq (head -> authorizing__users);
  268.     }
  269.  
  270.     if (head -> originator != NULL) {
  271.         if (head -> authorizing__users == NULL)
  272.             do_key    ("From");
  273.         else
  274.             do_key    ("Sender");
  275.         
  276.         do_ORD (head -> originator);
  277.     }
  278.  
  279.     if (head -> this__IPM != NULL)
  280.     {
  281.         do_key ("Message-ID");
  282.         if (do_mid (head -> this__IPM, TRUE) != OK) {
  283.             *ep = strdup("Invalid message id");
  284.             return NOTOK;
  285.         }
  286.     }
  287.  
  288.     if (head -> primary__recipients != NULL)
  289.     {
  290.         do_key ("To");
  291.         do_recip_seq (head -> primary__recipients);
  292.         haveTo = TRUE;
  293.     }
  294.  
  295.     if (head -> copy__recipients != NULL)
  296.     {
  297.         do_key ("Cc");
  298.         do_recip_seq (head -> copy__recipients);
  299.         haveTo = TRUE;
  300.     }
  301.     
  302.     if (head -> blind__copy__recipients != NULL)
  303.     {
  304.         do_key ("Bcc");
  305.         do_recip_seq (head -> blind__copy__recipients);
  306.         haveTo = TRUE;
  307.     }
  308.  
  309.     if (haveTo != TRUE) {
  310.         do_key ("To");
  311.         do_token ("list:;");
  312.     }
  313.  
  314.     if (head -> replied__to__IPM != NULL)
  315.     {
  316.         do_key ("In-Reply-To");
  317.         if (do_mid (head -> replied__to__IPM, FALSE) != OK) {
  318.             *ep = strdup("Invalid In-Reply-To message id");
  319.             return NOTOK;
  320.         }
  321.     }
  322.     
  323.     if (head -> obsoleted__IPMs != NULL)
  324.     {
  325.         do_key ("Obsoletes");
  326.         if (do_mid_seq (head -> obsoleted__IPMs, TRUE) != OK) {
  327.             *ep = strdup("Invalid Obsoletes message id");
  328.             return NOTOK;
  329.         }
  330.     }
  331.     
  332.     if (head -> related__IPMs != NULL)
  333.     {
  334.         do_key ("References");
  335.         if (do_mid_seq (head -> related__IPMs, FALSE) != OK) {
  336.             *ep = strdup("Invalid References message id");
  337.             return NOTOK;
  338.         }
  339.     }
  340.  
  341.     if (head -> subject != NULL)
  342.     {
  343.         do_key ("Subject");
  344.         do_subject (head -> subject);
  345.     }
  346.  
  347.     if (head -> expiry__time != NULL)
  348.     {
  349.         do_key ("Expiry-Date");
  350.         do_utc (head -> expiry__time);
  351.     }
  352.  
  353.     if (head -> reply__time != NULL)
  354.     {
  355.         do_key ("Reply-By");
  356.         do_utc (head -> reply__time);
  357.     }
  358.  
  359.     if (head -> reply__recipients != NULL)
  360.     {
  361.         do_key ("Reply-To");
  362.         do_ORD_seq (head -> reply__recipients);
  363.     }
  364.  
  365.     if (head -> importance != NULL
  366.         && head -> importance -> parm != int_IOB_ImportanceField_normal)
  367.     {
  368.         do_key ("Importance");
  369.         do_importance (head -> importance -> parm);
  370.     }
  371.  
  372.     if (head -> sensitivity != NULL)
  373.     {
  374.         do_key ("Sensitivity");
  375.         do_sensitivity (head -> sensitivity -> parm);
  376.     }
  377.  
  378.     if (head -> auto__forwarded != NULL
  379.         && head -> auto__forwarded -> parm)
  380.     {
  381.         do_key ("Autoforwarded");
  382.         do_boolean (head -> auto__forwarded -> parm);
  383.     }
  384.  
  385.     if (head -> extensions != NULL)
  386.         do_extensions (head -> extensions);
  387.  
  388.     return (OK);
  389. }
  390.  
  391. /* ARGSUSED */
  392. do_p2_ipn(qp, ep)
  393. Q_struct *qp;
  394. char    **ep;
  395. {
  396.     char    buf[BUFSIZ];
  397.     extern char    *postmaster;
  398.     ADDR    *ix;
  399.  
  400.     do_key ("From");
  401.     if (ipn->ipn__originator)
  402.         do_ORD (ipn->ipn__originator);
  403.     else if ((Q_struct *) NULL != qp)
  404.         do_p1_addrs (qp -> Oaddress);
  405.     else {
  406.         sprintf(buf, "%s", postmaster);
  407.         do_token(buf);
  408.     }
  409.     
  410.     
  411.     do_key ("To");
  412.     if ((Q_struct *) NULL != qp) {
  413.         for (ix = qp->Raddress;
  414.              ix != NULLADDR && ix -> ad_resp == NO;
  415.              ix = ix -> ad_next)
  416.             continue;
  417.         if (ix == NULLADDR)
  418.             ix = qp->Raddress;
  419.     
  420.         if (ix != NULLADDR) {
  421.             if (ix -> ad_redirection_history != (Redirection *) NULL) {
  422.                 if (ix->ad_redirection_history->rd_addr != NULLCP) {
  423.                     OR_ptr    or = or_std2or(ix->ad_redirection_history->rd_addr);
  424.                     or_or2rfc(or, buf);
  425.                     or_free(or);
  426.                 } else
  427.                     sprintf(buf,"list:;");
  428.                 
  429.                 if (ix -> ad_redirection_history -> rd_dn != NULLCP)
  430.                     (void) sprintf(buf, "%s (DN=%s)",
  431.                                buf,
  432.                                ix -> ad_redirection_history -> rd_dn);
  433.             } else
  434.                 (void) strcpy(buf, ix -> ad_r822adr);
  435.             do_token(buf);
  436.         } else
  437.             do_token("list:;");        
  438.     } else
  439.         do_token("list:;");
  440.  
  441.     do_key ("Subject");
  442.     do_token ("X.400 Inter-Personal Receipt Notification");
  443.  
  444.     do_key ("Message-Type");
  445.     do_token ("InterPersonal Notification");
  446.  
  447.     if (ipn -> subject__ipm != NULL)
  448.     {
  449.         do_key ("References");
  450.         if (do_mid (ipn -> subject__ipm, FALSE) != OK) {
  451.             *ep = strdup("Invalid References message id");
  452.             return NOTOK;
  453.         }
  454.     }
  455.  
  456.     return OK;
  457. }
  458.  
  459. do_p2_ipn_body (qp, ep)
  460. Q_struct    *qp;
  461. char    **ep;
  462. {
  463.     FILE    *fp;
  464.     char    buf[BUFSIZ];
  465.  
  466.     if (ipn_body[0] != '\0') {
  467.         if ((fp = fopen (ipn_body, "w")) == NULL)
  468.         {
  469.             PP_SLOG (LLOG_EXCEPTIONS, ipn_body,
  470.                  ("Can't open file"));
  471.             (void) sprintf(buf,
  472.                        "Unable to open output file '%s' for IPN body",
  473.                        ipn_body);
  474.             *ep = strdup(buf);
  475.             return (NOTOK);
  476.         }
  477.     } else 
  478.         fp = stdout;
  479.  
  480.     fputs("Your message to: ", fp);
  481.  
  482.     if (ipn -> ipn__preferred__recipient != NULL) {
  483.         get_ORD (ipn -> ipn__preferred__recipient, abuf);
  484.         fputs(abuf, fp);
  485.         if (ipn -> ipn__originator != NULL) {
  486.                        fputs(" forwarded to: ", fp);
  487.                        get_ORD (ipn -> ipn__originator, abuf);
  488.                        fputs(abuf, fp);
  489.            }
  490.     } else if (ipn -> ipn__originator != NULL) {
  491.                get_ORD (ipn -> ipn__originator, abuf);
  492.                fputs(abuf, fp);
  493.        } else if ((Q_struct *) NULL != qp
  494.           && adr2rfc (qp->Oaddress, abuf, order_pref) == OK)
  495.            fputs(abuf, fp);
  496.     else
  497.         fputs("an unknown recipient", fp);
  498.  
  499.     fputs("\n", fp);
  500.     if (ipn -> choice != NULL) {
  501.         if (ipn -> choice -> offset == choice_IOB_0_non__receipt__fields)
  502.             do_p2_ipn_body_non__receipt(ipn -> choice -> un.non__receipt__fields, fp);
  503.         else 
  504.             do_p2_ipn_body_receipt (ipn -> choice -> un.receipt__fields, fp);
  505.     }        
  506.     if (ipn -> conversion__eits != NULL) 
  507.         do_p2_ipn_body_eits (ipn -> conversion__eits, fp);
  508.         
  509.     
  510.     if (ipn -> choice != NULL &&
  511.         ipn -> choice -> offset == choice_IOB_0_non__receipt__fields) {
  512.         if (ipn -> choice -> un.non__receipt__fields -> returned__ipm != NULL)
  513.             fputs("\nThe Original Message follows: \n\n", fp);
  514.         else
  515.             fputs("\nThe Original Message is not available\n", fp);
  516.     } else
  517.         fputs("\nThe Original Message is not returned with positive notifications\n", fp);
  518.  
  519.     fclose (fp);
  520.     return (OK);
  521. }    
  522.  
  523. do_p2_ipn_body_non__receipt (non_receipt, fp)
  524. struct type_IOB_NonReceiptFields    *non_receipt;
  525. FILE                *fp;
  526. {
  527.     if (non_receipt -> non__receipt__reason -> parm == int_IOB_NonReceiptReasonField_ipm__discarded)
  528.         do_p2_ipn_discard (non_receipt, fp);
  529.     else
  530.         do_p2_ipn_auto_forward (non_receipt, fp);
  531. }
  532.  
  533. do_p2_ipn_discard (non_receipt, fp)
  534. struct type_IOB_NonReceiptFields    *non_receipt;
  535. FILE                *fp;
  536. {
  537.     fputs("was discarded for the following reason: ", fp);
  538.     switch (non_receipt -> discard__reason -> parm) {
  539.         case int_IOB_DiscardReasonField_ipm__expired:
  540.         fputs ("Expired.\n", fp);
  541.         break;
  542.         case int_IOB_DiscardReasonField_ipm__obsoleted:
  543.         fputs ("Obsoleted.\n", fp);
  544.         break;
  545.         case int_IOB_DiscardReasonField_user__subscription__terminated:
  546.         fputs ("User Subscription Terminated.\n", fp);
  547.         break;
  548.     }
  549. }
  550.  
  551. do_p2_ipn_auto_forward (non_receipt, fp)
  552. struct type_IOB_NonReceiptFields    *non_receipt;
  553. FILE                *fp;
  554. {
  555.     char    *cp;
  556.     fputs ("was automatically forwarded.\n", fp);
  557.     if (non_receipt -> auto__forward__comment != NULL) {
  558.         cp = qb2str(non_receipt -> auto__forward__comment);
  559.         fputs ("The following comment was made: ", fp);
  560.         fputs (cp, fp);
  561.         fputs (".\n", fp);
  562.         free (cp);
  563.     }
  564. }
  565.     
  566. do_p2_ipn_body_receipt (receipt, fp)
  567. struct type_IOB_ReceiptFields    *receipt;
  568. FILE                *fp;
  569. {
  570.     do_p2_utc (receipt -> receipt__time, fp);
  571.     fputs("\n", fp);
  572.     if (receipt -> acknowledgment__mode != NULL)
  573.         do_p2_ack_mode (receipt -> acknowledgment__mode, fp);
  574.     if (receipt -> suppl__receipt__info != NULL)
  575.         do_p2_suppl_info (receipt -> suppl__receipt__info, fp);
  576. }
  577.  
  578. do_p2_ack_mode (mode, fp)
  579. struct type_IOB_AcknowledgmentModeField    *mode;
  580. FILE    *fp;
  581. {
  582.     fputs ("This notification was generated ", fp);
  583.     if (mode -> parm == int_IOB_AcknowledgmentModeField_manual)
  584.         fputs("Manually.\n", fp);
  585.     else
  586.         fputs ("Automatically.\n", fp);
  587. }
  588.  
  589. do_p2_suppl_info (info, fp)
  590. struct type_IOB_SupplReceiptInfoField    *info;
  591. FILE     *fp;
  592. {
  593.     char    *cp;
  594.     fputs ("The following extra information was given:\n", fp);
  595.     cp = qb2str (info);
  596.     fputs(cp, fp);
  597.     fputs ("\n", fp);
  598.     free(cp);
  599. }
  600.  
  601. do_p2_ipn_body_eits (eits, fp)
  602. struct type_IOB_ConversionEITsField    *eits;
  603. FILE    *fp;
  604. {
  605.     int    first = OK;
  606.  
  607.     fputs ("The following information types were converted:", fp);
  608.     
  609.     if (bit_test (eits -> built__in__encoded__information__types,
  610.               bit_MTA_BuiltInEncodedInformationTypes_undefined) == 1) {
  611.         if (first == OK) {
  612.             fputs ("Undefined", fp);
  613.             first = NOTOK;
  614.         } else
  615.             fputs (", Undefined", fp);
  616.     }
  617.  
  618.     if (bit_test (eits -> built__in__encoded__information__types,
  619.               bit_MTA_BuiltInEncodedInformationTypes_telex) == 1) {
  620.         if (first == OK) {
  621.             fputs ("Telex", fp);
  622.             first = NOTOK;
  623.         } else
  624.             fputs (", Telex", fp);
  625.     }
  626.  
  627.     if (bit_test (eits -> built__in__encoded__information__types,
  628.               bit_MTA_BuiltInEncodedInformationTypes_ia5__text) == 1) {
  629.         if (first == OK) {
  630.             fputs ("IA5-Text", fp);
  631.             first = NOTOK;
  632.         } else
  633.             fputs (", IA5-Text", fp);
  634.     }
  635.  
  636.     if (bit_test (eits -> built__in__encoded__information__types,
  637.               bit_MTA_BuiltInEncodedInformationTypes_g3__facsimile) == 1) {
  638.         if (first == OK) {
  639.             fputs ("G3-Fax", fp);
  640.             first = NOTOK;
  641.         } else
  642.             fputs (", G3-Fax", fp);
  643.     }
  644.  
  645.     if (bit_test (eits -> built__in__encoded__information__types,
  646.               bit_MTA_BuiltInEncodedInformationTypes_g4__class__1) == 1) {
  647.         if (first == OK) {
  648.             fputs ("TIF0", fp);
  649.             first = NOTOK;
  650.         } else
  651.             fputs (", TIF0", fp);
  652.     }
  653.  
  654.     if (bit_test (eits -> built__in__encoded__information__types,
  655.               bit_MTA_BuiltInEncodedInformationTypes_teletex) == 1) {
  656.         if (first == OK) {
  657.             fputs ("Teletex", fp);
  658.             first = NOTOK;
  659.         } else
  660.             fputs (", Teletex", fp);
  661.     }
  662.     
  663.     if (bit_test (eits -> built__in__encoded__information__types,
  664.               bit_MTA_BuiltInEncodedInformationTypes_videotex) == 1) {
  665.         if (first == OK) {
  666.             fputs ("Videotex", fp);
  667.             first = NOTOK;
  668.         } else
  669.             fputs (", Videotex", fp);
  670.     }
  671.  
  672.     if (bit_test (eits -> built__in__encoded__information__types,
  673.               bit_MTA_BuiltInEncodedInformationTypes_voice) == 1) {
  674.         if (first == OK) {
  675.             fputs ("Voice", fp);
  676.             first = NOTOK;
  677.         } else
  678.             fputs (", Voice", fp);
  679.     }
  680.  
  681.     if (bit_test (eits -> built__in__encoded__information__types,
  682.               bit_MTA_BuiltInEncodedInformationTypes_sfd) == 1) {
  683.         if (first == OK) {
  684.             fputs ("SFD", fp);
  685.             first = NOTOK;
  686.         } else
  687.             fputs (", SFD", fp);
  688.     }
  689.  
  690.     if (bit_test (eits -> built__in__encoded__information__types,
  691.               bit_MTA_BuiltInEncodedInformationTypes_mixed__mode) == 1) {
  692.         if (first == OK) {
  693.             fputs ("TIF1", fp);
  694.             first = NOTOK;
  695.         } else
  696.             fputs (", TIF1", fp);
  697.     }
  698.  
  699.     if (eits -> external__encoded__information__types != NULL) {
  700.         if (first == OK) {
  701.             fputs (", ", fp);
  702.             first = NOTOK;
  703.         }
  704.         fputs (oid2lstr (eits -> external__encoded__information__types), fp);
  705.     }
  706.     fputs(".\n", fp);
  707. }
  708.  
  709. do_p2_utc (utc_qb, fp)
  710. struct qbuf    *utc_qb;
  711. FILE    *fp;
  712. {
  713.     char     *cp;
  714.     UTC    ut, lut;
  715.     fputs ("was received at ", fp);
  716.     cp = qb2str (utc_qb);
  717.     if ((ut = str2utct (cp, strlen(cp))) == NULL)
  718.         ut = str2gent (cp, strlen(cp));
  719.     lut = utclocalise(ut);
  720.     UTC2rfc (lut, abuf);
  721.     fputs(abuf, fp);
  722.     fputs(".\n", fp);
  723.     free(cp);
  724.     free ((char *)ut);
  725.     free ((char *)lut);
  726. }
  727.  
  728. /*   */
  729.  
  730. static int moreThanHdrAndIa5(eit)
  731. EncodedIT    *eit;
  732. {
  733.     LIST_BPT    *ix = eit->eit_types;
  734.     int        found = 0;
  735. static char        *p2_txt = NULLCP;
  736.     if (p2_txt == NULLCP)
  737.         p2_txt = rcmd_srch(BPT_P2_DLIV_TXT, bptbl_body_parts88);
  738.     while (found == 0 && ix != NULL) {
  739.         if (strncmp(hdr_822_bp, ix->li_name, strlen(hdr_822_bp)) == 0
  740.             || strncmp(p2_txt, ix->li_name, strlen(p2_txt)) == 0
  741.             || strncmp(hdr_p2_bp, ix->li_name, strlen(hdr_p2_bp)) == 0
  742.             || strncmp(ia5_bp, ix->li_name, strlen(ia5_bp)) == 0)
  743.             ix = ix->li_next;
  744.         else
  745.             /* not ia5 or hdr */
  746.             found = 1;
  747.     }
  748.     return found;
  749. }
  750.  
  751. /* ARGSUSED */
  752. do_p1 (qp, ishead, ep)
  753. Q_struct *qp;
  754. int     ishead;
  755. char    **ep;
  756. {
  757.     if (qp == (Q_struct *) 0)
  758.         return (OK);
  759.  
  760.     do_p1_trace (qp -> trace);
  761.     
  762.     do_key ("Date");
  763.  
  764.     do_p1_utc (qp -> trace->trace_DomSinfo.dsi_time);
  765.  
  766.     if (ishead == OK && head -> originator == NULL)
  767.     {
  768.         if (head -> authorizing__users == NULL)
  769.             do_key("From");
  770.         else
  771.             do_key("Sender");
  772.  
  773.         do_p1_addrs (qp -> Oaddress);
  774.     }
  775.  
  776.     do_key ("X400-Originator");
  777.     do_p1_addrs (qp -> Oaddress);
  778.  
  779.     if (ishead == OK &&
  780.         head -> primary__recipients == NULL &&
  781.         head -> copy__recipients == NULL &&
  782.         head -> blind__copy__recipients == NULL) 
  783.     {
  784.         do_key ("To");
  785.         if (qp -> disclose_recips
  786.             || qp -> Raddress -> ad_next == NULLADDR)
  787.             do_p1_addrs (qp -> Raddress);
  788.         else
  789.             do_token ("non-disclosure:;");
  790.     }
  791.  
  792.     do_key ("X400-Recipients");
  793.     if (qp -> disclose_recips 
  794.         || qp -> Raddress -> ad_next == NULLADDR)
  795.         do_p1_addrs (qp -> Raddress);
  796.     else
  797.         do_token ("non-disclosure:;");
  798.  
  799.     do_key ("X400-MTS-Identifier");
  800.     do_p1_mid (&(qp -> msgid));
  801.  
  802.     if (qp -> orig_encodedinfo.eit_types != NULL
  803.         && moreThanHdrAndIa5 (&qp -> orig_encodedinfo)) {
  804.         do_key ("Original-Encoded-Information-Types");
  805.         do_p1_eit (&(qp -> orig_encodedinfo));
  806.     } else if (qp -> encodedinfo.eit_types != NULL
  807.         && moreThanHdrAndIa5 (&qp -> encodedinfo)) {
  808.         /* not just ia5 bodypart */
  809.         do_key ("Original-Encoded-Information-Types");
  810.         do_p1_eit (&(qp -> encodedinfo));
  811.     }
  812.  
  813.     if (qp -> cont_type != NULLCP) {
  814.         do_key ("X400-Content-Type");
  815.         if (lexequ (qp -> cont_type, cont_p2) == 0)
  816.             do_token ("P2-1984 (2)");
  817.         else if (lexequ (qp -> cont_type, cont_p22) == 0)
  818.             do_token ("P2-1988 (22)");
  819.         else
  820.             do_token (qp -> cont_type);
  821.     }
  822.  
  823.     if (qp -> ua_id != NULLCP)
  824.     {
  825.         do_key ("Content-Identifier");
  826.         do_token (qp -> ua_id);
  827.     }
  828.  
  829.     if (qp -> priority != PRIO_NORMAL)
  830.     {
  831.         do_key ("Priority");
  832.         do_p1_priority (qp -> priority);
  833.     }
  834.     
  835.     if (qp -> originator_return_address != NULL)
  836.     {
  837.         do_key ("Originator-Return-Address");
  838.         do_p1_fullname (qp -> originator_return_address);
  839.     }
  840.     
  841.     if (qp -> dl_expansion_history != NULL)
  842.         do_p1_DLHistory (qp -> dl_expansion_history);
  843.  
  844.     if (qp -> implicit_conversion_prohibited == TRUE) 
  845.     {
  846.         do_key("Conversion");
  847.         do_token("Prohibited");
  848.     }
  849.         
  850.     if (qp -> conversion_with_loss_prohibited)
  851.     {
  852.         do_key ("Conversion-With-Loss");
  853.         do_token ("Prohibited");
  854.     }
  855.     
  856.     
  857.        if (qp -> defertime != 0)
  858.        {
  859.            do_key ("Deferred-Delivery");
  860.            do_p1_utc (qp -> defertime);
  861.        }
  862.     
  863.     if (qp -> latest_time != 0
  864.         && qp -> latest_time_crit)
  865.     {
  866.         do_key ("Latest-Delivery-Time");
  867.         do_p1_utc (qp -> latest_time);
  868.     }
  869.  
  870.     return (OK);
  871. }
  872.  
  873. /* ARGSUSED */
  874. do_p1_ipn (qp, ishead, ep)
  875. Q_struct *qp;
  876. int     ishead;
  877. char    **ep;
  878. {
  879.     if (qp == (Q_struct *) 0)
  880.         return (OK);
  881.  
  882.     do_p1_trace (qp -> trace);
  883.     
  884.     do_key ("Date");
  885.  
  886.     do_p1_utc (qp -> trace->trace_DomSinfo.dsi_time);
  887.  
  888.     do_key ("X400-Originator");
  889.     do_p1_addrs (qp -> Oaddress);
  890.  
  891.     do_key ("X400-MTS-Identifier");
  892.     do_p1_mid (&(qp -> msgid));
  893.  
  894.     if (qp -> cont_type != NULLCP) {
  895.         do_key ("X400-Content-Type");
  896.         if (lexequ (qp -> cont_type, cont_p2) == 0)
  897.             do_token ("P2-1984 (2)");
  898.         else if (lexequ (qp -> cont_type, cont_p22) == 0)
  899.             do_token ("P2-1988 (22)");
  900.         else
  901.             do_token (qp -> cont_type);
  902.     }
  903.  
  904.     if (qp -> orig_encodedinfo.eit_types != NULL
  905.         && moreThanHdrAndIa5 (&qp -> orig_encodedinfo)) {
  906.         do_key ("Original-Encoded-Information-Types");
  907.         do_p1_eit (&(qp -> orig_encodedinfo));
  908.     } else if (qp -> encodedinfo.eit_types != NULL
  909.         && moreThanHdrAndIa5 (&qp -> encodedinfo)) {
  910.         /* not just ia5 bodypart */
  911.         do_key ("Original-Encoded-Information-Types");
  912.         do_p1_eit (&(qp -> encodedinfo));
  913.     }
  914.  
  915.     if (qp -> priority != PRIO_NORMAL)
  916.     {
  917.         do_key ("Priority");
  918.         do_p1_priority (qp -> priority);
  919.     }
  920.  
  921.     if (qp -> ua_id != NULLCP)
  922.     {
  923.         do_key ("Content-Identifier");
  924.         do_token (qp -> ua_id);
  925.     }
  926.  
  927.     return (OK);
  928. }
  929.  
  930. /*   */
  931.  
  932. do_extra (extra, ep)
  933. char *extra;
  934. char    **ep;
  935. {
  936.     char buf [BUFSIZ], tmp[BUFSIZ];
  937.     FILE *fp_extra;
  938.  
  939.     if (extra == NULLCP || extra [0] == '\0')
  940.         return (OK);
  941.  
  942.     if ((fp_extra = fopen (extra, "r")) == NULL)
  943.     {
  944.         PP_SLOG (LLOG_EXCEPTIONS, extra,
  945.              ("Can't open file"));
  946.         (void) sprintf (tmp,
  947.                 "Unable to open extra input file '%s'", 
  948.                 extra); 
  949.         *ep = strdup(tmp);
  950.         return (NOTOK);
  951.     }
  952.  
  953.     if (fgets (buf, BUFSIZ - 1, fp_extra) == NULL)
  954.     {
  955.         PP_DBG (( "Null file '%s'", extra));
  956.         (void) sprintf (tmp,
  957.                 "Empty extra file '%s'", 
  958.                 extra);
  959.         *ep = strdup(tmp);
  960.         fclose (fp_extra);
  961.         return (NOTOK);
  962.     }
  963.  
  964.     buf [strlen(buf) - 1] = '\0';  /* remvove \n */
  965.     if (lexnequ (buf, "RFC-822-HEADERS", 
  966.              strlen("RFC-822-HEADERS")) != 0
  967.         && lexnequ (buf, "Comments", 
  968.             strlen("Comments")) != 0)
  969.     {
  970.         PP_DBG (( "Illegal first line '%s' in file '%s'",
  971.                 buf, extra));
  972.         (void) sprintf (tmp,
  973.                 "Illegal first line '%s' in file '%s'",
  974.                 buf, extra);
  975.         fclose (fp_extra);
  976.         *ep = strdup(tmp);
  977.         return (NOTOK);
  978.     }
  979.  
  980.     while (TRUE)
  981.     {
  982.         if ((fgets (buf, BUFSIZ -1, fp_extra) == NULL) 
  983.             && !feof (fp_extra))
  984.         {
  985.             PP_DBG (( "File read error"));
  986.             fclose (fp_extra);
  987.             return (NOTOK);
  988.         }
  989.  
  990.         if (!feof (fp_extra))
  991.             fputs (buf, fp_out);
  992.         else
  993.         {
  994.             fclose (fp_extra);
  995.             return (OK);
  996.         }
  997.     }
  998.  
  999. }
  1000.  
  1001. /*   */
  1002. /* P2 structure bits */
  1003. do_822_extension_88 (pe)
  1004. PE    pe;
  1005. {
  1006.     char    *hdr_txt, *cix;
  1007.  
  1008.     struct type_IOB_RFC822FieldList     *list, *ix;
  1009.     PY_pepy[0] = 0;
  1010.     if (decode_IOB_RFC822FieldList (pe, 0, NULLIP, NULLVP, &list) != OK)
  1011.         PP_OPER(NULLCP,
  1012.             ("decode_IOB_RFC822Field () Failed : [%s]", PY_pepy));
  1013.     else {
  1014.         for (ix = list; ix != NULL; ix = ix -> next) {
  1015.             hdr_txt = qb2str(ix->RFC822Field);
  1016.             if ((cix = index(hdr_txt, ':')) == NULLCP) {
  1017.                 PP_LOG(LLOG_EXCEPTIONS,
  1018.                    ("Unable to parse extra 822 hdr '%s'", hdr_txt));
  1019.                 free(hdr_txt);
  1020.                 continue;
  1021.             }
  1022.             *cix++ = '\0';
  1023.             while (isspace(*cix)) cix++;
  1024.             do_key(hdr_txt);
  1025.             do_token (cix);
  1026.             free(hdr_txt);
  1027.         }
  1028.         free_IOB_RFC822FieldList(list);
  1029.     }
  1030. }
  1031.  
  1032. do_822_extension_84 (pe)
  1033. PE      pe;
  1034. {
  1035.         char    *hdr_txt, *ix;
  1036.  
  1037.         struct type_IOB_RFC822Field      *hdr;
  1038.         PY_pepy[0] = 0;
  1039.         if (decode_IOB_RFC822Field (pe, 0, NULLIP, NULLVP, &hdr) != OK)
  1040.                 PP_OPER(NULLCP,
  1041.                         ("decode_IOB_RFC822Field () Failed : [%s]", PY_pepy));
  1042.         else {
  1043.                 hdr_txt = qb2str(hdr);
  1044.                 if ((ix = index(hdr_txt, ':')) == NULLCP) {
  1045.                         PP_LOG(LLOG_EXCEPTIONS,
  1046.                                ("Unable to parse extra 822 hdr '%s'", hdr_txt));
  1047.                         free(hdr_txt);
  1048.                         return;
  1049.                 }
  1050.                 *ix++ = '\0';
  1051.                 while (isspace(*ix)) ix++;
  1052.                 do_key(hdr_txt);
  1053.                 do_token (ix);
  1054.                 free(hdr_txt);
  1055.                 free_IOB_RFC822Field(hdr);
  1056.         }
  1057. }
  1058.  
  1059. static char    discard_extn[BUFSIZ];
  1060.  
  1061. do_discarded_extensions    ()
  1062. {
  1063.     do_key ("Discarded-X400-IPMS-Extensions");
  1064.     do_token(discard_extn);
  1065. }
  1066.  
  1067. do_incomplete_copy()
  1068. {
  1069.     do_key ("Incomplete-Copy");
  1070.     do_token ("");
  1071. }
  1072.  
  1073. do_languages (pe)
  1074. PE    pe;
  1075. {
  1076.     char    *lang_txt;
  1077.  
  1078.     struct type_IOB_Languages    *lang, *ix;
  1079.     PY_pepy[0] = 0;
  1080.     if (decode_IOB_Languages (pe, 0, NULLIP, NULLVP, &lang) != OK)
  1081.         PP_OPER(NULLCP,
  1082.             ("decode_IOB_Languages () failed : [%s]", PY_pepy));
  1083.     else {
  1084.         ix = lang;
  1085.         while (ix != NULL) {
  1086.             lang_txt = qb2str(ix -> Language);
  1087.             do_key ("Language");
  1088.             do_token (lang_txt);
  1089.             free(lang_txt);
  1090.             ix = ix -> next;
  1091.         }
  1092.         free_IOB_Languages(lang);
  1093.     }
  1094. }
  1095.     
  1096.         
  1097. do_extension (extension)
  1098. struct type_IOB_HeadingExtension    *extension;
  1099. {
  1100.     OID    oid;
  1101.  
  1102.     if (extension -> type == NULL) {
  1103.         PP_LOG(LLOG_EXCEPTIONS,
  1104.                ("NULL oid in header extension"));
  1105.         return;
  1106.     }
  1107.     if ((oid = str2oid(id_rfc_822_field_list)) == NULLOID) {
  1108.         PP_LOG(LLOG_EXCEPTIONS,
  1109.                ("Unable to convert '%s' to an OID",
  1110.             id_rfc_822_field_list));
  1111.     }
  1112.         
  1113.     if (oid != NULLOID
  1114.         && oid_cmp (extension -> type, oid) == 0)
  1115.         return do_822_extension_88 (extension -> value);
  1116.  
  1117.     if ((oid = str2oid(id_rfc_822_field)) == NULLOID) {
  1118.         PP_LOG(LLOG_EXCEPTIONS,
  1119.                ("Unable to convert '%s' to an OID",
  1120.             id_rfc_822_field));
  1121.     }
  1122.     
  1123.     if (oid != NULLOID
  1124.         && oid_cmp (extension -> type, oid) == 0)
  1125.         return do_822_extension_84 (extension -> value);
  1126.  
  1127.     if ((oid = str2oid(id_hex_incomplete_copy)) == NULLOID) {
  1128.         PP_LOG(LLOG_EXCEPTIONS,
  1129.                ("Unable to convert '%s' to an OID",
  1130.             id_hex_incomplete_copy));
  1131.     }
  1132.     
  1133.     if (oid != NULLOID
  1134.         && oid_cmp (extension -> type, oid) == 0)
  1135.         return do_incomplete_copy();
  1136.  
  1137.     if ((oid = str2oid(id_hex_languages)) == NULLOID) {
  1138.         PP_LOG(LLOG_EXCEPTIONS,
  1139.                ("Unable to convert '%s' to an OID",
  1140.             id_hex_languages));
  1141.     }
  1142.     
  1143.     if (oid != NULLOID
  1144.         && oid_cmp (extension -> type, oid) == 0)
  1145.         return do_languages (extension -> value);
  1146.  
  1147.     PP_LOG(LLOG_EXCEPTIONS,
  1148.            ("Unrecognised oid '%s' in header extension", 
  1149.         oid2lstr(extension -> type)));
  1150.     if ('\0' != discard_extn[0])
  1151.         strcat(discard_extn, ", ");
  1152.     strcat(discard_extn, oid2lstr(extension -> type));
  1153. }
  1154.  
  1155. do_extensions (extensions)
  1156. struct type_IOB_ExtensionsField    *extensions;
  1157. {
  1158.     discard_extn[0] = '\0';
  1159.     while (extensions != NULL) {
  1160.         do_extension (extensions -> HeadingExtension);
  1161.         extensions = extensions -> next;
  1162.     }
  1163.     if ('\0' != discard_extn[0])
  1164.         do_discarded_extensions();
  1165. }
  1166.  
  1167. static CHARSET    *ia5 = (CHARSET *) NULL;
  1168. static CHARSET    *t61 = (CHARSET *) NULL;
  1169.  
  1170. static CHAR8U *t61toasc (t61str)
  1171. CHAR8U    *t61str;
  1172. {
  1173.     CHAR8U    *ia5str;
  1174.     
  1175.     if (ia5 == (CHARSET *) NULL)
  1176.         ia5 = getchset("CCITT_T.50.irv:1988", (INT16S) 29);
  1177.     if (t61 == (CHARSET *) NULL)
  1178.         t61 = getchset("T.61-8bit", (INT16S) 29);
  1179.  
  1180.     if (ia5 != (CHARSET *) NULL
  1181.         && t61 != (CHARSET *) NULL) {
  1182.         ia5str = (CHAR8U *) malloc(sizeof(CHAR8U) * strlen((char *) t61str)+1);
  1183.         if (strncnv (ia5, t61, 
  1184.                  ia5str, t61str, 
  1185.                  strlen((char *) t61str),FALSE) >= 0)
  1186.             return ia5str;
  1187.     } 
  1188.     return (CHAR8U *) NULL;
  1189. }
  1190.  
  1191. do_subject (qb)
  1192. struct qbuf *qb;
  1193. {
  1194.     CHAR8U *t61str, *ia5str;
  1195.     t61str = (CHAR8U *) qb2str (qb);
  1196.     if ((ia5str = t61toasc((CHAR8U *) t61str)) != (CHAR8U *) NULL) {
  1197.         do_string (ia5str);
  1198.         free(ia5str);
  1199.     } else
  1200.         do_string (t61str);
  1201.     free (t61str);
  1202. }
  1203.  
  1204.  
  1205. do_recip_seq (recip_seq)
  1206. struct type_IOB_RecipientSequence *recip_seq;
  1207. {
  1208.     struct type_IOB_RecipientSpecifier *recip;
  1209.  
  1210.     recip = recip_seq -> RecipientSpecifier;
  1211.     get_ORD (recip -> recipient, abuf);
  1212.  
  1213.     if (recip -> notification__requests != NULLPE &&
  1214.         bit_test (recip -> notification__requests,
  1215.                 bit_IOB_NotificationRequests_rn) == 1) {
  1216.         strcat (abuf, " (Receipt Notification Requested)");
  1217.     }
  1218.  
  1219.     if (recip -> notification__requests != NULLPE &&
  1220.         bit_test (recip -> notification__requests,
  1221.                 bit_IOB_NotificationRequests_nrn) == 1) {
  1222.         strcat (abuf, " (Non Receipt Notification Requested)");
  1223.     }
  1224.  
  1225.     if (recip -> notification__requests != NULLPE &&
  1226.         bit_test (recip -> notification__requests,
  1227.                 bit_IOB_NotificationRequests_ipm__return) == 1) {
  1228.         strcat (abuf, " (IPM Return Requested)");
  1229.     }
  1230.  
  1231.     if (recip -> reply__requested)
  1232.         strcat (abuf, " (Reply Requested)");
  1233.  
  1234.     do_token (abuf);
  1235.     if (recip_seq -> next != NULL)
  1236.     {
  1237.         do_same_line (",");
  1238.         do_recip_seq (recip_seq -> next);
  1239.     }
  1240. }
  1241.  
  1242.  
  1243.  
  1244. do_ORD_seq (ord_seq)
  1245. struct type_IOB_ORDescriptorSequence *ord_seq;
  1246. {
  1247.     get_ORD (ord_seq -> ORDescriptor, abuf);
  1248.     do_token (abuf);
  1249.     if (ord_seq -> next != NULL)
  1250.     {
  1251.         do_same_line (",");
  1252.         do_ORD_seq (ord_seq -> next);
  1253.     }
  1254. }
  1255.  
  1256.  
  1257. do_ORD (ord)
  1258. struct type_IOB_ORDescriptor *ord;
  1259. {
  1260.     get_ORD (ord, abuf);
  1261.     do_token (abuf);
  1262. }
  1263.  
  1264. OR_ptr pe2or();
  1265.  
  1266. static void add_phrase(out, in)
  1267. char    *out, *in;
  1268. {
  1269.     AP_ptr    tree = NULLAP, group, name, local, domain, route;
  1270.     
  1271.     if (ap_s2p(in, &tree, &group, &name, 
  1272.            &local, &domain, &route) != (char *) NOTOK
  1273.         && route != NULLAP && group == NULLAP) {
  1274.         char    *str;
  1275.         group = ap_new(AP_PERSON_NAME, local->ap_obvalue);
  1276.         str = ap_p2s(group, name, local, domain, route);
  1277.         strcpy (out, str);
  1278.         free(str);
  1279.         ap_free(group);
  1280.     } else
  1281.         strcpy (out, in);
  1282.  
  1283.     if (tree != NULLAP) {
  1284.         ap_sqdelete (tree, NULLAP);
  1285.         ap_free (tree);
  1286.     }
  1287. }
  1288.  
  1289. get_ORD (ord, buf)
  1290. struct type_IOB_ORDescriptor *ord;
  1291. char *buf;
  1292. {
  1293.     /* see rfc1138 4.7.2 */
  1294.     ORName *orn;
  1295.     char tbuf [BUFSIZ], asc[BUFSIZ];
  1296.     char *cp, *str = NULLCP, *dn = NULLCP;
  1297.  
  1298.     if ((orn = orname2orn(ord -> formal__name)) == NULLORName) {
  1299.         PP_DBG (("Failed to convert IOB_orname to ORName"));
  1300.         tbuf[0] = '\0';
  1301.     } else {
  1302.         if (or_or2rfc (orn->on_or, tbuf) != OK) {
  1303.             PP_DBG (("or_or2rfc failed"));
  1304.             tbuf[0] = '\0';
  1305.         }
  1306.         if (orn->on_dn != NULL)
  1307.             dn = dn2ufn (orn->on_dn, FALSE);
  1308.         ORName_free(orn);
  1309.     }
  1310.  
  1311.     if (ord -> free__form__name == NULL) 
  1312.         if (tbuf[0] == '\0')
  1313.             strcpy (buf, "Empty Address :;");
  1314.         else
  1315.             if (tbuf[0] == '@')
  1316.                 sprintf (buf, "FOO <%s>", tbuf);
  1317.             else 
  1318.                 /* if route add phrase */
  1319.                 add_phrase(buf, tbuf);
  1320.  
  1321.     else
  1322.     {
  1323.         CHAR8U    *t61str, *ia5str;
  1324.         
  1325.         t61str = (CHAR8U *) qb2str (ord -> free__form__name);
  1326.  
  1327.         /* do t.61 -> ascii conversion */
  1328.         if ((ia5str = t61toasc((CHAR8U *) t61str)) != (CHAR8U *) NULL) {
  1329.             strcpy (asc, (char *) ia5str);
  1330.             free((char *) ia5str);
  1331.         } else
  1332.             strcpy (asc, (char *) t61str);
  1333.         
  1334.         if (tbuf [0] == '\0')
  1335.             sprintf (buf, "\"%s\" :;", asc);
  1336.         else
  1337.             sprintf (buf, "\"%s\" <%s>", asc, tbuf);
  1338.         free ((char *) t61str);
  1339.     }
  1340.  
  1341.     if (dn != NULLCP)
  1342.     {
  1343.         strcat (buf, " (DN=");
  1344.         strcat (buf, dn);
  1345.         strcat (buf, ")");
  1346.         free(dn);
  1347.     }
  1348.  
  1349.     if (ord -> telephone__number != NULL)
  1350.     {
  1351.         cp = qb2str (ord -> telephone__number);
  1352.         if (*cp != '\0') {
  1353.             strcat (buf, " (Tel ");
  1354.             strcat (buf, cp);
  1355.             strcat (buf, ")");
  1356.             free(cp);
  1357.         }
  1358.     }
  1359.     ap_s2s (buf, &str, order_pref);
  1360.     if (str != NULLCP
  1361.         && *str != '\0') {
  1362.         (void) strcpy(buf, str);
  1363.         free(str);
  1364.     }
  1365. }
  1366.  
  1367. do_mid_seq (mid_seq, addMHS)
  1368. struct type_IOB_IPMIdentifierSequence *mid_seq;
  1369. int    addMHS;
  1370. {
  1371.     if (do_mid (mid_seq -> IPMIdentifier, addMHS) != OK)
  1372.         return NOTOK;
  1373.     if (mid_seq -> next != NULL)
  1374.     {
  1375.         do_same_line (",");
  1376.         return do_mid_seq (mid_seq -> next, addMHS);
  1377.     }
  1378.     return OK;
  1379. }
  1380.  
  1381. extern char *loc_dom_site;
  1382.  
  1383. do_mid (mid, addMHS)
  1384. struct type_IOB_IPMIdentifier *mid;
  1385. int    addMHS;
  1386. {
  1387.     char *midstring;
  1388.     ORName    *orn;
  1389.     char tbuf [BUFSIZ], buf[BUFSIZ];
  1390.     char *cp;
  1391.     AP_ptr ap;
  1392.     AP_ptr local;
  1393.     AP_ptr domain;
  1394.     /* see rfc 1138 4.7.3.4 */
  1395.  
  1396.     if (mid -> user__relative__identifier != NULL) {
  1397.         midstring = qb2str (mid -> user__relative__identifier);
  1398.         or_ps2asc (midstring, abuf);
  1399.         free(midstring);
  1400.  
  1401.         if (lexequ(abuf, "RFC-822") == 0)
  1402.             return do_mid_987(mid);
  1403.  
  1404.         if (mid -> user == NULL) {
  1405.             (void) sprintf (buf, "<%s>", abuf);
  1406.             if ((index(buf, '@') != NULLCP)
  1407.                 && (ap_s2p (buf, &ap, (AP_ptr *) 0, (AP_ptr *) 0, 
  1408.                        &local, &domain, 
  1409.                        (AP_ptr *) 0) != (char *) NOTOK)) {
  1410.                 /* buf parses as 822.msg-id */
  1411.                 do_token (buf);
  1412.                 ap_free(ap);
  1413.                 return OK;
  1414.             }
  1415.         }
  1416.     } else
  1417.         abuf[0] = '\0';
  1418.  
  1419.     /* try as x400 generated */
  1420.     if (mid -> user) {
  1421.         if ((orn = orname2orn (mid -> user)) != NULLORName) {
  1422.             or_or2std (orn->on_or, tbuf, FALSE);
  1423.             if (abuf[0] != '\0')
  1424.                 sprintf (buf, "%s*%s", abuf, tbuf);
  1425.             else
  1426.                 sprintf (buf, "*%s", tbuf);
  1427.  
  1428.             local = ap_new (AP_MAILBOX, buf);
  1429.             domain = ap_new (AP_DOMAIN, "MHS");
  1430.             cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP);
  1431.             sprintf (abuf, "<%s>", cp);
  1432.             free (cp);
  1433.             ap_free (local);
  1434.             ap_free (domain); 
  1435.             ORName_free(orn);
  1436.             do_token (abuf);
  1437.             return OK;
  1438.         }
  1439.     }
  1440.  
  1441.     /* no user */
  1442.     if (abuf[0] != '\0') {
  1443.         if (addMHS == TRUE) {
  1444.             (void) sprintf(buf, "%s*",abuf);
  1445.             local = ap_new(AP_MAILBOX, buf);
  1446.             domain = ap_new(AP_DOMAIN, "MHS");
  1447.             cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP);
  1448.             sprintf (abuf, "<%s>", cp);
  1449.             ap_free (domain); 
  1450.         } else {
  1451.             /* generate phrase as 1148 4.7.3.5 says */
  1452.             local = ap_new (AP_GROUP_NAME, abuf);
  1453.             cp = ap_p2s_nc(local, NULLAP, NULLAP, NULLAP, NULLAP);
  1454.             strcpy(abuf, cp);
  1455.         }
  1456.         free (cp);
  1457.         ap_free (local);
  1458.         do_token (abuf);
  1459.         return OK;
  1460.     }
  1461.  
  1462.     PP_DBG (( "Highly dubious ID"));
  1463.     (void) sprintf (abuf, "<FOO@%s>", loc_dom_site);
  1464.     do_token(abuf);
  1465.     /* gen mid */
  1466.     return NOTOK;
  1467. }
  1468.  
  1469. do_mid_987(mid)
  1470. struct type_IOB_IPMIdentifier    *mid;
  1471. {
  1472.     char    buf[BUFSIZ], buf2[BUFSIZ];
  1473.     ORName    *orn;
  1474.  
  1475.     if (mid -> user) {
  1476.         if ((orn = orname2orn(mid->user)) != NULLORName
  1477.             && orn->on_or != NULLOR
  1478.             && or_or2rfc_aux(orn->on_or, buf, FALSE) == OK) {
  1479.             (void) sprintf(buf2, "<%s>",buf);
  1480.             do_token (buf2);
  1481.             ORName_free(orn);
  1482.             return OK;
  1483.         }
  1484.         if (orn) ORName_free(orn);
  1485.     }
  1486.  
  1487.     PP_DBG(("Highly dubious 987 ID"));
  1488.     (void) sprintf(buf, "<FOO@%s>", loc_dom_site);
  1489.     do_token(buf);
  1490.     return NOTOK;
  1491. }
  1492.  
  1493. do_utc (utc_qb)
  1494. struct qbuf *utc_qb;
  1495. {
  1496.     char *cp;
  1497.     UTC    ut;
  1498.  
  1499.     cp = qb2str (utc_qb);
  1500.     ut = str2utct (cp, strlen(cp));
  1501.     do_p1_utc (ut);
  1502.     free (cp);
  1503. }
  1504.  
  1505. do_importance (importance)
  1506. int importance;
  1507. {
  1508.     switch (importance)
  1509.     {
  1510.         case int_IOB_ImportanceField_low:
  1511.             do_token ("Low");
  1512.             break;
  1513.         case int_IOB_ImportanceField_normal:
  1514.             do_token ("Normal");
  1515.             break;
  1516.         case int_IOB_ImportanceField_high:
  1517.             do_token ("High");
  1518.             break;
  1519.             default:
  1520.             sprintf(abuf, "Undefined (value=%d)", importance);
  1521.             do_token (abuf);
  1522.             break;
  1523.     }
  1524. }
  1525.  
  1526. do_sensitivity (sensitivity)
  1527. int sensitivity;
  1528. {
  1529.     switch (sensitivity)
  1530.     {
  1531.         case int_IOB_SensitivityField_personal:
  1532.             do_token ("Personal");
  1533.             break;
  1534.         case int_IOB_SensitivityField_private:
  1535.             do_token ("Private");
  1536.             break;
  1537.         case int_IOB_SensitivityField_company__confidential:
  1538.             do_token ("Company-Confidential");
  1539.             break;
  1540.             default:
  1541.             sprintf(abuf, "Undefined (value=%d)", sensitivity);
  1542.             do_token (abuf);
  1543.             break;
  1544.     }
  1545. }
  1546.  
  1547. do_boolean (bool)
  1548. char bool;
  1549. {
  1550.     if (bool)
  1551.         do_token ("TRUE");
  1552.     else
  1553.         do_token ("FALSE");
  1554. }
  1555.  
  1556. /*   */
  1557. /* Stuff for P1 */
  1558.  
  1559. do_p1_utc (ut)
  1560. UTC    ut;
  1561. {
  1562.     UTC    lut;
  1563.     lut = utclocalise(ut);
  1564.     if (UTC2rfc (lut, abuf) == NOTOK)
  1565.         strcpy(abuf, ">>INVALID UTC TIME<<");
  1566.     do_token (abuf);
  1567.     free((char *) lut);
  1568. }
  1569.  
  1570. do_p1_addrs (addr)
  1571. ADDR *addr;
  1572. {
  1573.     if (adr2rfc (addr, abuf, order_pref) == OK)
  1574.         do_token (abuf);
  1575.     if (addr -> ad_next != NULL)
  1576.     {
  1577.         do_same_line (",");
  1578.         do_p1_addrs (addr -> ad_next);
  1579.     }
  1580. }
  1581.  
  1582. do_p1_mid (mid)
  1583. MPDUid *mid;
  1584. {
  1585.     msgid2rfc (mid, abuf); 
  1586.     do_token (abuf);
  1587. }
  1588.  
  1589. do_p1_eit (eit)
  1590. EncodedIT *eit;
  1591. {
  1592.     x400eits2rfc (eit, abuf); 
  1593.     do_token (abuf);
  1594. }
  1595.  
  1596. do_p1_priority (priority)
  1597. int priority;
  1598. {
  1599.     switch (priority)
  1600.     {
  1601.         case PRIO_NORMAL:
  1602.             do_token ("Normal");
  1603.             break;
  1604.         case PRIO_URGENT:
  1605.             do_token ("Urgent");
  1606.             break;
  1607.         case PRIO_NONURGENT:
  1608.             do_token ("Non-Urgent");
  1609.             break;
  1610.     }
  1611. }
  1612.  
  1613. do_p1_trace (trace)
  1614. Trace *trace;
  1615. {
  1616.  
  1617.     if (trace->trace_next != NULL)
  1618.         do_p1_trace(trace->trace_next);
  1619.     do_key ("X400-Received");
  1620.     x400trace2rfc (trace,abuf);
  1621.     do_token (abuf);
  1622. }
  1623.  
  1624. do_p1_fullname (fullname)
  1625. FullName    *fullname;
  1626. {
  1627.     do_token (fullname->fn_addr);
  1628. }
  1629.  
  1630. do_p1_DLHistory (history)
  1631. DLHistory    *history;
  1632. {
  1633.     char    temp[BUFSIZ];
  1634.     OR_ptr    or;
  1635.     UTC    lut;
  1636.     if (history -> dlh_next != NULL)
  1637.         do_p1_DLHistory(history -> dlh_next);
  1638.     do_key ("DL-Expansion-History");
  1639.     or = or_std2or(history -> dlh_addr);
  1640.     or_or2rfc_aux(or, temp, FALSE);
  1641.     (void) sprintf (abuf,
  1642.             "%s",
  1643.             temp);
  1644.     if (history -> dlh_time != 0) {
  1645.         lut = utclocalise(history -> dlh_time);
  1646.         UTC2rfc (lut, temp);
  1647.         free ((char *) lut);
  1648.         (void) sprintf (abuf,
  1649.                 "%s ; %s;",
  1650.                 abuf, temp);
  1651.     }
  1652.     do_token (abuf);
  1653. }
  1654.             
  1655.  
  1656. /*   */
  1657. /* General purpose header output */
  1658.  
  1659. do_key (key)
  1660. char *key;
  1661. {
  1662.     if (firstLine != TRUE) 
  1663.         fputs ("\n", fp_out);
  1664.     else
  1665.         firstLine = FALSE;
  1666.     fputs (key, fp_out);
  1667.     fputs (": ", fp_out);
  1668. }
  1669.  
  1670. do_string (string)              /* fold string on spaces for unstructured */
  1671. char *string;
  1672. {
  1673.     fputs (" ", fp_out);
  1674.     fputs (string, fp_out);
  1675. }
  1676.  
  1677. do_same_line (token)
  1678. char *token;
  1679. {
  1680.     fputs (token, fp_out);
  1681. }
  1682.  
  1683. do_token (token)
  1684. char *token;
  1685. {
  1686.     fputs (" ", fp_out);
  1687.     fputs (token, fp_out);
  1688. }
  1689.  
  1690. /*   */
  1691.  
  1692. do_delinfo (file, ep)
  1693. char    *file;
  1694. char    **ep;
  1695. {
  1696.     FILE    *fp_in;
  1697.     PE    pe = NULLPE;
  1698.     PS    ps = NULLPS;
  1699.     struct type_IOB_MessageParameters *params = (struct type_IOB_MessageParameters *) NULL;
  1700.     char    buf[BUFSIZ];
  1701.  
  1702.     if ((fp_in = fopen (file, "r")) == NULL)
  1703.     {
  1704.         PP_SLOG (LLOG_EXCEPTIONS, file,
  1705.             ("Can't open file for reading"));
  1706.         fclose (fp_in);
  1707.         (void) sprintf (buf,
  1708.                 "Failed to open input file '%s'",
  1709.                 file);
  1710.         *ep = strdup(buf);
  1711.         return NOTOK;
  1712.     }
  1713.  
  1714.     if (((ps = ps_alloc (std_open)) == NULLPS) ||
  1715.         (std_setup (ps, fp_in) == NOTOK))
  1716.     {
  1717.         PP_LOG (LLOG_EXCEPTIONS, ("p2to822() failed to setup PS"));
  1718.         *ep = strdup("Failed to set up PS");
  1719.         fclose(fp_in);
  1720.         if (ps) ps_free(ps);
  1721.         return NOTOK;
  1722.     }
  1723.  
  1724.  
  1725.     if ((pe = ps2pe (ps)) == NULLPE)
  1726.     {
  1727.         PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error on file '%s'", file));
  1728.         fclose (fp_in);
  1729.         if (pe) pe_free(pe);
  1730.         if (ps) ps_free(ps);
  1731.     }
  1732.  
  1733.     PY_pepy[0] = 0;
  1734.     if (decode_IOB_MessageParameters(pe, 0, NULLIP, NULLVP, ¶ms) != OK)
  1735.     {
  1736.         PP_OPER(NULLCP,
  1737.             ("decode_IOB_MessageParameters() failed : [%s]", PY_pepy));
  1738.         convertresult = NOTOK;
  1739.         *ep = strdup("Illegal ASN.1 in forwarded message parameters");
  1740.         fclose (fp_in);
  1741.         if (pe) pe_free(pe);
  1742.         if (ps) ps_free(ps);
  1743.         if (params) free_IOB_MessageParameters(params);
  1744.         return NOTOK;
  1745.     }
  1746.     if (0 != PY_pepy[0])
  1747.         PP_LOG(LLOG_EXCEPTIONS,
  1748.                ("decode_IOB_MessageParameters non-fatal failure [%s]",
  1749.             PY_pepy));
  1750.     if (params->delivery__time)
  1751.         do_delivery_time(params->delivery__time);
  1752.     if (params->delivery__envelope)
  1753.         do_delivery_envelope(params->delivery__envelope);
  1754.     fclose (fp_in);
  1755.     if (pe) pe_free(pe);
  1756.     if (ps) ps_free(ps);
  1757.     if (params) free_IOB_MessageParameters(params);
  1758.     return OK;
  1759. }
  1760.  
  1761. do_delivery_time(time)
  1762. struct type_MTA_MessageDeliveryTime *time;
  1763. {
  1764.     do_key("Delivery-Date");
  1765.     do_utc(time);
  1766. }
  1767.  
  1768. do_delivery_envelope(envelope)
  1769. struct type_MTA_OtherMessageDeliveryFields    *envelope;
  1770. {
  1771.     char    buf[BUFSIZ];
  1772.  
  1773.     do_key("X400-Content-Type");
  1774.     switch (envelope->member_MTA_8->offset) {
  1775.         case choice_MTA_4_built__in:
  1776.         do_built_in_content(envelope->member_MTA_8->un.built__in);
  1777.         break;
  1778.         case choice_MTA_4_external:
  1779.         do_external_content (envelope->member_MTA_8->un.external);
  1780.         break;
  1781.     }
  1782.     
  1783.     if (head -> originator == NULL
  1784.         && head -> authorizing__users == NULL)
  1785.         do_key ("From");
  1786.     else
  1787.         do_key("X400-Originator");
  1788.     do_MTA_ORName(envelope->originator__name, buf);
  1789.     do_token(buf);
  1790.  
  1791.     if (envelope->original__encoded__information__types != NULL) {
  1792.         do_key ("Original-Encoded-Information-Types");
  1793.         do_MTA_eits (envelope->original__encoded__information__types);
  1794.     }
  1795.  
  1796.     if (envelope->priority 
  1797.         && envelope->priority->parm != int_MTA_Priority_normal) {
  1798.         do_key ("Priority");
  1799.         do_MTA_priority (envelope->priority->parm);
  1800.     }
  1801.  
  1802.     if (envelope->delivery__flags
  1803.         && bit_ison (envelope->delivery__flags,
  1804.              bit_MTA_DeliveryFlags_implicit__conversion__prohibited)) {
  1805.         do_key("Conversion");
  1806.         do_token("Prohibited");
  1807.     }
  1808.  
  1809.     if (envelope->this__recipient__name) {
  1810.         do_key("X400-Recipients");
  1811.         do_MTA_this_recipient(envelope->this__recipient__name,
  1812.                       envelope->originally__intended__recipient__name);
  1813.     }
  1814.  
  1815.     if (envelope->converted__encoded__information__types != NULL) {
  1816.         do_key ("Converted-Encoded-Information-Types");
  1817.         do_MTA_eits (envelope->converted__encoded__information__types);
  1818.     }
  1819.  
  1820.     if (envelope->other__recipient__names) {
  1821.         do_key("X400-Recipients");
  1822.         do_MTA_other_recips(envelope->other__recipient__names);
  1823.     }
  1824.     
  1825.     do_key("Date");
  1826.     do_utc(envelope->message__submission__time);
  1827.  
  1828.     if (envelope->content__identifier) {
  1829.         char    *str = qb2str(envelope->content__identifier);
  1830.         do_key("Content-Identifier");
  1831.         do_token(str);
  1832.         free(str);
  1833.     }
  1834.  
  1835.     if (envelope->extensions)
  1836.         do_MTA_extensions(envelope->extensions);
  1837.     
  1838. }
  1839.  
  1840. do_MTS_discard_extensions ()
  1841. {
  1842.     do_key ("Discarded-X400-MTS-Extensions");
  1843.     do_token(discard_extn);
  1844. }
  1845.  
  1846. do_MTA_extensions(extns)
  1847. struct type_MTA_Extensions *extns;
  1848. {
  1849.     bzero((char *) &del_info_q, sizeof(del_info_q));
  1850.     bzero((char *) &del_info_recip, sizeof(del_info_recip));
  1851.  
  1852.     discard_extn[0] = '\0';
  1853.     while (extns != (struct type_MTA_Extensions *) NULL) {
  1854.         switch (extns->ExtensionField->type->offset) {
  1855.             case type_MTA_ExtensionType_local:
  1856.             do_MTA_local_extension (extns->ExtensionField);
  1857.             break;
  1858.             case type_MTA_ExtensionType_global:
  1859.             do_MTA_global_extension (extns->ExtensionField);
  1860.             break;
  1861.         }
  1862.         extns = extns -> next;
  1863.     }
  1864.     if ('\0' != discard_extn[0])
  1865.         do_MTS_discard_extensions();
  1866. }
  1867.  
  1868. do_MTA_local_extension (ext)
  1869. struct type_MTA_ExtensionField *ext;
  1870. {
  1871.     PP_LOG(LLOG_EXCEPTIONS,
  1872.            ("Unknown local extension '%s'",
  1873.         oid2lstr(ext->type->un.local)));
  1874.     if ('\0' != discard_extn[0])
  1875.         strcat (discard_extn, ", ");
  1876.     strcat(discard_extn, oid2lstr(ext->type->un.local));
  1877. }
  1878.  
  1879. do_MTA_global_extension (ext)
  1880. struct type_MTA_ExtensionField *ext;
  1881. {
  1882.     char    buffer[BUFSIZ];
  1883.     switch (ext->type->un.global) {
  1884.         case EXT_CONVERSION_WITH_LOSS_PROHIBITED:
  1885.         if (decode_extension
  1886.             ((caddr_t) &(del_info_q.conversion_with_loss_prohibited),
  1887.              _ZConversionWithLossProhibitedExt,
  1888.              &_ZExt_mod,
  1889.              "Extensions.ConversionWithLossProhibited",
  1890.              decode_ext_char,
  1891.              ext) == OK
  1892.             && del_info_q.conversion_with_loss_prohibited) {
  1893.             do_key ("Conversion-With-Loss");
  1894.             do_token("Prohibited");
  1895.         }
  1896.         break;
  1897.         case EXT_REQUESTED_DELIVERY_METHOD:
  1898.         if (decode_extension
  1899.             ((caddr_t)del_info_recip.ad_req_del,
  1900.              _ZRequestedDeliveryMethodExt,
  1901.              &_ZExt_mod,
  1902.              "Extensions.RequestedDeliveryMethod",
  1903.              decode_ext_rdm,
  1904.              ext) == OK) {
  1905.             if (del_info_recip.ad_req_del[0] != AD_RDM_NOTUSED
  1906.                 && del_info_recip.ad_req_del[0] != AD_RDM_ANY) {
  1907.                 int     ix = 0, first = OK;
  1908.                 char    *type;
  1909.  
  1910.                 do_key("Requested-Delivery-Methods");
  1911.                 buffer[0] = '\0';
  1912.                 while (ix < AD_RDM_MAX 
  1913.                        && del_info_recip.ad_req_del[ix] != AD_RDM_NOTUSED
  1914.                        && del_info_recip.ad_req_del[ix] != AD_RDM_ANY) {
  1915.                     if ((type = rcmd_srch(del_info_recip.ad_req_del[ix], atbl_rdm)) != NULLCP) {
  1916.                         if (OK != first )
  1917.                             strcat(buffer, ", ");
  1918.                         strcat(buffer,
  1919.                                type);
  1920.                     }
  1921.                     ix++;
  1922.                     first = NOTOK;
  1923.                 }
  1924.                 do_token(buffer);
  1925.             }
  1926.         }
  1927.         break;
  1928.         case EXT_ORIGINATOR_RETURN_ADDRESS:
  1929.         do_MTA_orig_ret_addr (ext);
  1930.         break;
  1931.         case EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST:
  1932.         decode_extension 
  1933.             ((caddr_t)&(del_info_recip.ad_phys_fw_ad_req),
  1934.              _ZPhysicalForwardingAddressRequestExt,
  1935.              &_ZExt_mod,
  1936.              "Extensions.PhysicalForwardingAddressRequest",
  1937.              decode_ext_char,
  1938.              ext);
  1939.         break;
  1940.         case EXT_PHYSICAL_DELIVERY_MODES:
  1941.         decode_extension
  1942.             ((caddr_t)&(del_info_recip.ad_phys_modes),
  1943.              _ZPhysicalDeliveryModesExt,
  1944.              &_ZExt_mod,
  1945.              "Extensions.PhysicalDeliveryModes",
  1946.              decode_ext_pdm,
  1947.              ext);
  1948.         break;
  1949.         case EXT_REGISTERED_MAIL:
  1950.         decode_extension
  1951.             ((caddr_t)&(del_info_recip.ad_reg_mail_type),
  1952.              _ZRegisteredMailTypeExt,
  1953.  
  1954.              &_ZExt_mod,
  1955.              "Extensions.RegisteredMailType",
  1956.              decode_ext_int,
  1957.              ext);
  1958.         break;
  1959.         case EXT_RECIPIENT_NUMBER_FOR_ADVICE:
  1960.         decode_extension
  1961.             ((caddr_t)&(del_info_recip.ad_recip_number_for_advice),
  1962.                  _ZRecipientNumberForAdviceExt,
  1963.                  &_ZExt_mod,
  1964.                  "Extensions.RecipientNumberForAdvice",
  1965.                  decode_ext_rnfa,
  1966.                  ext);
  1967.         break;
  1968.         case EXT_PHYSICAL_RENDITION_ATTRIBUTES:
  1969.         decode_extension
  1970.             ((caddr_t)&(del_info_recip.ad_phys_rendition_attribs),
  1971.              _ZPhysicalRenditionAttributesExt,
  1972.              &_ZExt_mod,
  1973.              "Extensions.PhysicalRenditionAttributes",
  1974.              decode_ext_pra,
  1975.              ext);
  1976.         break;
  1977.         case EXT_PHYSICAL_DELIVERY_REPORT_REQUEST:
  1978.         decode_extension
  1979.             ((caddr_t)&(del_info_recip.ad_pd_report_request),
  1980.              _ZPhysicalDeliveryReportRequestExt,
  1981.              &_ZExt_mod,
  1982.              "Extensions.PhysicalDeliveryReportRequest",
  1983.              decode_ext_int,
  1984.              ext);
  1985.         break;
  1986.         case EXT_PHYSICAL_FORWARDING_PROHIBITED:
  1987.         decode_extension
  1988.             ((caddr_t)&(del_info_recip.ad_phys_forward),
  1989.              _ZPhysicalForwardingProhibitedExt,
  1990.              &_ZExt_mod,
  1991.              "Extensions.PhysicalForwardingProhibited",
  1992.              decode_ext_char,
  1993.              ext);
  1994.         break;
  1995.         case EXT_REDIRECTION_HISTORY:
  1996.         decode_extension
  1997.             ((caddr_t)&(del_info_recip.ad_redirection_history),
  1998.              _ZRedirectionHistoryExt,
  1999.              &_ZExt_mod,
  2000.              "Extensions.RedirectionHistory",
  2001.              decode_ext_redir,
  2002.              ext);
  2003.  
  2004.         break;
  2005.         case EXT_DL_EXPANSION_HISTORY:
  2006.         if (decode_extension
  2007.             ((caddr_t)&(del_info_q.dl_expansion_history),
  2008.              _ZDLExpansionHistoryExt,
  2009.              &_ZExt_mod,
  2010.              "Extensions.DLExpansionHistory",
  2011.              ext_decode_dlexph,
  2012.              ext) == OK)
  2013.             do_p1_DLHistory (del_info_q.dl_expansion_history);
  2014.         break;
  2015.         default:
  2016.         break;
  2017.     }
  2018. }
  2019.  
  2020. do_MTA_orig_ret_addr(ext)
  2021. struct type_MTA_ExtensionField *ext;
  2022. {
  2023.     struct type_Ext_OriginatorReturnAddress *ora;
  2024.     OR_ptr    or;
  2025.     char    buf[BUFSIZ];
  2026.  
  2027.     if (decode_Ext_OriginatorReturnAddress (ext -> value, 1,
  2028.                            NULLIP, NULLVP,
  2029.                            &ora) == NOTOK) {
  2030.         PP_LOG (LLOG_EXCEPTIONS,
  2031.             ("Can't parse originator return address [%s]",
  2032.              PY_pepy));
  2033.         return;
  2034.     }
  2035.  
  2036.     or = oradr2ora (ora);
  2037.     
  2038.     if (or_or2rfc(or, buf) == OK) {
  2039.         do_key("Originator-Return-Address");
  2040.         do_token(buf);
  2041.     }
  2042.     or_free(or);
  2043.     free_Ext_OriginatorReturnAddress (ora);
  2044. }
  2045.  
  2046. do_MTA_eits (eits)
  2047. struct type_MTA_EncodedInformationTypes *eits;
  2048. {
  2049.     int    some;
  2050.  
  2051.     some = do_MTA_buildin_eits(eits->built__in__encoded__information__types);
  2052.     if (eits->external__encoded__information__types) {
  2053.         if (TRUE == some)
  2054.             do_same_line(",");
  2055.         do_MTA_external_eits(eits->external__encoded__information__types);
  2056.     }
  2057. }
  2058.  
  2059. do_MTA_external_eits(eits)
  2060. struct type_MTA_ExternalEncodedInformationTypes    *eits;
  2061. {
  2062.     int some = FALSE;
  2063.  
  2064.     while (eits != (struct type_MTA_ExternalEncodedInformationTypes *) NULL) {
  2065.         if (TRUE == some)
  2066.             do_same_line(",");
  2067.         else
  2068.             some = TRUE;
  2069.         do_token (oid2lstr(eits->ExternalEncodedInformationType));
  2070.         eits = eits -> next;
  2071.     }
  2072. }
  2073.  
  2074. do_MTA_buildin_eits (eits)
  2075. struct type_MTA_BuiltInEncodedInformationTypes    *eits;
  2076. {
  2077.     int    some = FALSE;
  2078.  
  2079.     if (bit_ison(eits,
  2080.              bit_MTA_BuiltInEncodedInformationTypes_undefined)) {
  2081.         do_token("undefined (0)");
  2082.         some = TRUE;
  2083.     }
  2084.     if (bit_ison(eits,
  2085.              bit_MTA_BuiltInEncodedInformationTypes_telex)) {
  2086.         if (TRUE == some)
  2087.             do_same_line(",");
  2088.         else
  2089.             some = TRUE;
  2090.         do_token("telex (1)");
  2091.     }
  2092.     if (bit_ison(eits,
  2093.              bit_MTA_BuiltInEncodedInformationTypes_ia5__text)) {
  2094.         if (TRUE == some)
  2095.             do_same_line(",");
  2096.         else
  2097.             some = TRUE;
  2098.         do_token("ia5 text (2)");
  2099.     }
  2100.     if (bit_ison(eits,
  2101.              bit_MTA_BuiltInEncodedInformationTypes_g3__facsimile)) {
  2102.         if (TRUE == some)
  2103.             do_same_line(",");
  2104.         else
  2105.             some = TRUE;
  2106.         do_token("g3 facsimile (3)");
  2107.     }
  2108.     if (bit_ison(eits,
  2109.              bit_MTA_BuiltInEncodedInformationTypes_g4__class__1)) {
  2110.         if (TRUE == some)
  2111.             do_same_line(",");
  2112.         else
  2113.             some = TRUE;
  2114.         do_token("g4 class 1 (4)");
  2115.     }
  2116.     if (bit_ison(eits,
  2117.              bit_MTA_BuiltInEncodedInformationTypes_teletex)) {
  2118.         if (TRUE == some)
  2119.             do_same_line(",");
  2120.         else
  2121.             some = TRUE;
  2122.         do_token("teletex (5)");
  2123.     }
  2124.     if (bit_ison(eits,
  2125.              bit_MTA_BuiltInEncodedInformationTypes_videotex)) {
  2126.         if (TRUE == some)
  2127.             do_same_line(",");
  2128.         else
  2129.             some = TRUE;
  2130.         do_token("videotex (6)");
  2131.     }
  2132.     if (bit_ison(eits,
  2133.              bit_MTA_BuiltInEncodedInformationTypes_voice)) {
  2134.         if (TRUE == some)
  2135.             do_same_line(",");
  2136.         else
  2137.             some = TRUE;
  2138.         do_token("voice (7)");
  2139.     }
  2140.     if (bit_ison(eits,
  2141.              bit_MTA_BuiltInEncodedInformationTypes_sfd)) {
  2142.         if (TRUE == some)
  2143.             do_same_line(",");
  2144.         else
  2145.             some = TRUE;
  2146.         do_token("sfd (8)");
  2147.     }
  2148.     if (bit_ison(eits,
  2149.              bit_MTA_BuiltInEncodedInformationTypes_mixed__mode)) {
  2150.         if (TRUE == some)
  2151.             do_same_line(",");
  2152.         else
  2153.             some = TRUE;
  2154.         do_token("mixed mode (9)");
  2155.     }
  2156.  
  2157.     return some;
  2158. }
  2159.  
  2160.  
  2161.     
  2162. do_MTA_priority (priority)
  2163. int priority;
  2164. {
  2165.     switch (priority)
  2166.     {
  2167.         case int_MTA_Priority_normal:
  2168.         do_token ("Normal");
  2169.         break;
  2170.         case int_MTA_Priority_urgent:
  2171.         do_token ("Urgent");
  2172.         break;
  2173.         case int_MTA_Priority_non__urgent:
  2174.         do_token ("Non-Urgent");
  2175.         break;
  2176.     }
  2177. }
  2178.  
  2179. do_MTA_ORName (orname, buf)
  2180. struct type_MTA_ORName *orname;
  2181. char    *buf;
  2182. {
  2183.     ORName    *orn;
  2184.     char    tbuf[BUFSIZ], *dn = NULLCP;
  2185.  
  2186.     if ((orn = orname2orn((struct type_IOB_ORName *) orname)) == NULLORName) {
  2187.         PP_DBG (("Failed to convert MTA_orname to ORName"));
  2188.         sprintf(buf, "");
  2189.         return;
  2190.     } else {
  2191.         if (or_or2rfc (orn->on_or, tbuf) != OK) {
  2192.             PP_DBG (("or_or2rfc failed"));
  2193.             tbuf[0] = '\0';
  2194.         }
  2195.         if (orn->on_dn != NULL)
  2196.             dn = dn2ufn (orn->on_dn, FALSE);
  2197.         ORName_free(orn);
  2198.     }
  2199.  
  2200.     if (dn != NULLCP) {
  2201.         sprintf(buf, "%s (DN=%s)",
  2202.             tbuf, dn);
  2203.         free(dn);
  2204.     } else
  2205.         strcpy(buf, tbuf);
  2206. }
  2207.     
  2208. do_MTA_other_recips (list)
  2209. struct type_MTA_OtherRecipientNames *list;
  2210. {
  2211.     char    buf[BUFSIZ];
  2212.     while (list != (struct type_MTA_OtherRecipientNames *) NULL) {
  2213.         do_MTA_ORName (list -> OtherRecipientName, buf);
  2214.         do_token(buf);
  2215.         list = list -> next;
  2216.         if (list != (struct type_MTA_OtherRecipientNames *) NULL) 
  2217.             do_same_line (",");
  2218.     }
  2219. }
  2220.  
  2221. do_MTA_this_recipient (recip, orig)
  2222. struct type_MTA_ORName    *recip, *orig;
  2223. {
  2224.     char    buf[BUFSIZ];
  2225.     do_MTA_ORName(recip, buf);
  2226.     if (orig != (struct type_MTA_ORName *) NULL) {
  2227.         char    tmp[BUFSIZ], tmp2[BUFSIZ];
  2228.         do_MTA_ORName(orig, tmp);
  2229.         sprintf(tmp2, "(Originally To: %s Redirected)",
  2230.             tmp);
  2231.         strcat(buf, tmp2);
  2232.     }
  2233.     adr2comments(&del_info_recip, buf);
  2234.     do_token(buf);
  2235. }
  2236.  
  2237. do_built_in_content(content)
  2238. struct type_MTA_BuiltInContentType *content;
  2239. {
  2240.     char    buf[BUFSIZ];
  2241.  
  2242.     switch (content->parm) {
  2243.         case int_MTA_BuiltInContentType_unidentified:
  2244.         do_token("unidentified (0)");
  2245.         break;
  2246.         case int_MTA_BuiltInContentType_external:
  2247.         do_token("external (1)");
  2248.         break;
  2249.         case int_MTA_BuiltInContentType_interpersonal__messaging__1984:
  2250.         do_token("P2-1984 (2)");
  2251.         break;
  2252.         case int_MTA_BuiltInContentType_interpersonal__messaging__1988:
  2253.         do_token("P2-1988 (22)");
  2254.         break;
  2255.         default:
  2256.         sprintf(buf, "unknown (%d)",
  2257.             content->parm);
  2258.         do_token (buf);
  2259.         break;
  2260.     }
  2261. }
  2262.  
  2263. do_external_content (content)
  2264. OID    content;
  2265. {
  2266.     do_token (oid2lstr(content));
  2267. }
  2268.  
  2269.  
  2270. /* nicked from x40088 */
  2271. static int decode_extension (value, magic_num, mod,
  2272.                  label, decoder, ext)
  2273. caddr_t    value;
  2274. int    magic_num;
  2275. modtyp    *mod;
  2276. IFP    decoder;
  2277. char    *label;
  2278. struct type_MTA_ExtensionField *ext;
  2279. {
  2280.     caddr_t *genp;
  2281.     int retval;
  2282.  
  2283. #if PP_DEBUG > 0
  2284.     if (pp_log_norm -> ll_events & LLOG_PDUS)
  2285.         pvpdu (pp_log_norm, magic_num, mod, 
  2286.             ext -> value, label, PDU_READ);
  2287. #endif
  2288.     if (dec_f(magic_num, mod, ext -> value, 1,
  2289.           NULLIP, NULLVP, &genp) == NOTOK) {
  2290.         PP_LOG (LLOG_EXCEPTIONS,
  2291.             ("Can't parse %s value [%s]", label, PY_pepy));
  2292.         return DONE;
  2293.     }
  2294.  
  2295.     if ((retval = (*decoder) (value, genp)) != OK)
  2296.         return retval;
  2297.  
  2298.     fre_obj((char *) genp, mod->md_dtab[magic_num], mod, 1);
  2299.     return OK;
  2300. }
  2301.  
  2302. static int decode_ext_char (cp, ptr)
  2303. char *cp;
  2304. struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */
  2305. {
  2306.     *cp = ptr -> parm;
  2307.     return OK;
  2308. }
  2309.  
  2310. static int decode_ext_rdm (value, genp)
  2311. int    value[AD_RDM_MAX];
  2312. struct type_Ext_RequestedDeliveryMethod *genp;
  2313. {
  2314.     int i;
  2315.     
  2316.     for (i = 0; i < AD_RDM_MAX && genp;
  2317.          i++, genp = genp -> next)
  2318.         value[i] = genp -> element_Ext_0;
  2319.     return OK;
  2320. }
  2321.  
  2322. static int decode_ext_pdm (value, genp)
  2323. int    *value;
  2324. PE    genp;
  2325. {
  2326. #define setbit(t,v) \
  2327.     (*value) |= (bit_ison(genp, (t)) ? (v) : 0)
  2328.  
  2329.     setbit (bit_Ext_PhysicalDeliveryModes_ordinary__mail,
  2330.         AD_PM_ORD);
  2331.     setbit (bit_Ext_PhysicalDeliveryModes_special__delivery,
  2332.         AD_PM_SPEC);
  2333.     setbit (bit_Ext_PhysicalDeliveryModes_express__mail,
  2334.         AD_PM_EXPR);
  2335.     setbit (bit_Ext_PhysicalDeliveryModes_counter__collection,
  2336.         AD_PM_CNT);
  2337.     setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telephone__advice,
  2338.         AD_PM_CNT_PHONE);
  2339.     setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__telex__advice,
  2340.         AD_PM_CNT_TLX);
  2341.     setbit (bit_Ext_PhysicalDeliveryModes_counter__collection__with__teletex__advice,
  2342.         AD_PM_CNT_TTX);
  2343.     setbit (bit_Ext_PhysicalDeliveryModes_bureau__fax__delivery,
  2344.         AD_PM_CNT_BUREAU);
  2345. #undef setbit
  2346.     return OK;
  2347. }
  2348.  
  2349. static int decode_ext_int (ip, ptr)
  2350. int *ip;
  2351. struct type_Ext_DLExpansionProhibited *ptr; /* any integer type will do */
  2352. {
  2353.     *ip = ptr -> parm;
  2354.     return OK;
  2355. }
  2356.  
  2357. static int decode_ext_rnfa (value, genp)
  2358. char    **value;
  2359. struct qbuf *genp;
  2360. {
  2361.     if ((*value = qb2str (genp)) == NULL)
  2362.         return NOTOK;
  2363.     return OK;
  2364. }
  2365.  
  2366. static int decode_ext_pra (value, gen)
  2367. OID    *value;
  2368. OID    gen;
  2369. {
  2370.     if ((*value = oid_cpy (gen)) != NULLOID)
  2371.         return OK;
  2372.     return NOTOK;
  2373. }
  2374.  
  2375.  
  2376. static int decode_1redir (rpp, redir)
  2377. Redirection **rpp;
  2378. struct type_Ext_Redirection *redir;
  2379. {
  2380.     ADDR *ad;
  2381.     int retval;
  2382.  
  2383.     *rpp = (Redirection *) smalloc (sizeof **rpp);
  2384.     if ((retval =
  2385.          load_addr (&ad, redir -> intended__recipient__name -> address))
  2386.         != OK)
  2387.         return retval;
  2388.     (*rpp) -> rd_addr = ad -> ad_value;
  2389.     ad -> ad_value = NULLCP;
  2390.     (*rpp) -> rd_dn = ad -> ad_dn;
  2391.     ad -> ad_dn = NULLCP;
  2392.     adr_free (ad);
  2393.  
  2394.     if ((retval = load_time (&(*rpp) -> rd_time,
  2395.                  redir -> intended__recipient__name -> redirection__time)) != OK)
  2396.         return retval;
  2397.     (*rpp) -> rd_reason = redir -> redirection__reason -> parm;
  2398.     return OK;
  2399. }
  2400.  
  2401. static int decode_ext_redir (value, genp)
  2402. Redirection **value;
  2403. struct type_Ext_RedirectionHistory *genp;
  2404. {
  2405.     int retval;
  2406.  
  2407.     while (genp) {
  2408.         if ((retval = decode_1redir (value, genp->Redirection)) != OK)
  2409.             return retval;
  2410.         value = &(*value) -> rd_next;
  2411.         genp = genp -> next;
  2412.     }
  2413.     return OK;
  2414. }
  2415.  
  2416. static int ext_decode_dlh (dlp, dpp)
  2417. struct type_Ext_DLExpansion *dlp;
  2418. DLHistory **dpp;
  2419. {
  2420.     UTC    ut;
  2421.     ADDR    *ad;
  2422.     int retval;
  2423.  
  2424.     if ((retval = load_time (&ut, dlp -> dl__expansion__time)) != OK)
  2425.         return retval;
  2426.     if ((retval = load_addr (&ad, dlp -> address)) != OK)
  2427.         return retval;
  2428.  
  2429.     *dpp = dlh_new (ad -> ad_value, ad -> ad_dn , ut);
  2430.     adr_free (ad);
  2431.  
  2432.     free ((char *)ut);
  2433.     return OK;
  2434. }
  2435.  
  2436. static int ext_decode_dlexph (dpp, genp)
  2437. DLHistory **dpp;
  2438. struct type_Ext_DLExpansionHistory *genp;
  2439. {
  2440.     struct type_Ext_DLExpansionHistory *dlhp;
  2441.     DLHistory *dp;
  2442.     int retval;
  2443.  
  2444.     for (dlhp = genp; dlhp; dlhp = dlhp -> next) {
  2445.         if ((retval = ext_decode_dlh (dlhp -> DLExpansion, &dp)) != OK)
  2446.             return retval;
  2447.         dlh_add (dpp, dp);
  2448.     }
  2449.     return OK;
  2450. }
  2451.  
  2452.  
  2453. static int load_time (utc, utcstr)
  2454. UTC    *utc;
  2455. struct type_UNIV_UTCTime *utcstr;
  2456. {
  2457.     char *str = qb2str (utcstr);
  2458.     if (str == NULLCP)
  2459.         return NOTOK;
  2460.     *utc = str2utct (str, strlen(str));
  2461.     if (*utc == NULLUTC)
  2462.         return NOTOK;
  2463.     free (str);
  2464.     *utc = utcdup (*utc);
  2465.     return *utc ? OK : NOTOK;
  2466. }
  2467.  
  2468. static int load_addr (app, orname)
  2469. ADDR    **app;
  2470. struct type_MTA_ORName *orname;
  2471. {
  2472.     ORName *orn;
  2473.     char    buf[BUFSIZ];
  2474.     ADDR    *ap;
  2475.  
  2476.     if ((orn = orname2orn (orname)) == NULL)
  2477.         return NOTOK;
  2478.  
  2479.     or_or2std (orn -> on_or, buf, 0);
  2480.     *app = ap  = adr_new (buf, AD_X400_TYPE, 1);
  2481.     ap -> ad_subtype = AD_X400_88;
  2482.  
  2483.     if (orn -> on_dn)
  2484.         ap -> ad_dn = dn2str (orn -> on_dn);
  2485.     ORName_free (orn);
  2486.     return OK;
  2487. }
  2488.